package com.fsoft.core.aop;

import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.web.servlet.ShiroHttpServletResponse;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.fsoft.core.utils.OgnlUtils;
import com.fsoft.core.xss.XssHttpServletRequestWrapper;

/***
 * F-Soft 基础切面类
 * @package com.fsoft.core.aop
 * @author Fish
 * @email it.fish2010@foxmail.com
 * @date 2019-12-11
 * @CopyRight © F-Soft
 */
@Aspect
@Component
@Order(0)
public class BaseAspect {

	private static Logger log = LoggerFactory.getLogger(BaseAspect.class);
	private long beginTime;
	private long endTime;

	private StringBuffer params;

	/**
	 * F-Soft 横切关注点 - 处理全局的请求绑定 <Br>
	 * 主要用于实时更新 BaseController 的各项属性
	 * @author it_software(it.fish2010@foxmail.com)
	 * @date 2020-02-20
	 * @param joinPoint
	 * @throws Exception
	 */
	@Before("execution(* com.fsoft..*.*Controller.*(..))")
	public void requestBind(JoinPoint joinPoint) throws Exception {
		beginTime = System.currentTimeMillis();
		this.params = new StringBuffer();
		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
		response.addHeader("Access-Control-Allow-Origin", "*");
		// 请求的参数
		Object[] args = joinPoint.getArgs();
		for (Object arg : args) {
			try {
				if (arg instanceof XssHttpServletRequestWrapper || arg instanceof ShiroHttpServletResponse)
					continue;
				if (OgnlUtils.isNotEmpty(arg))
					params.append(JSON.toJSONString(arg));
			} catch (Exception e) {
				log.warn("AOP存在无法识别的请求参数 :" + e.getMessage());
			}
		}
	}

	/**
	 * F-Soft 统计所有 Controller 中的方法运行耗时
	 * @author it_software(it.fish2010@foxmail.com)
	 * @date 2020-02-20
	 * @param joinPoint
	 */
	@After("execution(* com.fsoft..*.*Controller.*(..))")
	public void timeWatch(JoinPoint joinPoint) {
		endTime = System.currentTimeMillis();
		String className = joinPoint.getTarget().getClass().getSimpleName();
		String methodName = joinPoint.getSignature().getName();
		StringBuffer msg = new StringBuffer(className + "." + methodName);
		msg.append("() 运行耗时：" + (endTime - beginTime) + " ms");
		if (params.length() > 0) {
			msg.append(",参数=").append(params);
		}
		log.info(msg.toString());
	}
}
